package com.xyy.saas.payment.converter;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.xyy.ec.order.business.dto.OrderRefundBusinessDto;
import com.xyy.ec.order.business.dto.pay.OrderPayBusinessDto;
import com.xyy.ec.order.dto.pay.OrderTransDto;
import com.xyy.ec.order.dto.refund.OrderRefundDto;
import com.xyy.saas.payment.adpater.jdCredit.resp.LoanInfoResponse;
import com.xyy.saas.payment.adpater.jdCredit.resp.RepayPlan;
import com.xyy.saas.payment.adpater.pingxx.domain.PayDO;
import com.xyy.saas.payment.common.model.Tuple2;
import com.xyy.saas.payment.dao.model.LoanRepayPlanDetailPo;
import com.xyy.saas.payment.dao.model.LoanRepayPlanPo;
import com.xyy.saas.payment.dao.model.OrderTransDataPo;
import com.xyy.saas.payment.dao.model.PayResultOrder;
import com.xyy.saas.payment.cores.enums.ComEnums;
import com.xyy.saas.payment.util.AmountCastUtil;
import com.xyy.saas.payment.util.AssertUtil;
import com.xyy.saas.payment.util.NumberUtil;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author liujf
 */
public class PayCommonConverter {

    public static List<OrderTransDataPo> buildTransDataPos(List<OrderPayBusinessDto> payDtoList, Map<String, PayResultOrder> resultOrderMap, Map<String, List<OrderRefundBusinessDto>> refundDtoMap) {
        List<OrderTransDataPo> transDataPos = new ArrayList<>();
        for (OrderPayBusinessDto businessDto : payDtoList) {
            PayResultOrder resultOrder = resultOrderMap.get(businessDto.getTargetOrderId());
            // 订单交易数据
            OrderTransDataPo transDataPo = new OrderTransDataPo();
            setComFields(transDataPo, businessDto, resultOrder);
            transDataPo.setBillType(ComEnums.BillTypeEnum.ORDER.getCode());
            transDataPos.add(transDataPo);

            // 退款单交易数据
            transDataPos.addAll(buildRefundTransOrderPos(businessDto, resultOrder, refundDtoMap.get(businessDto.getOrderNo())));
        }


        return transDataPos;
    }

    private static List<OrderTransDataPo> buildRefundTransOrderPos(OrderPayBusinessDto businessDto, PayResultOrder resultOrder, List<OrderRefundBusinessDto> refundDtoList) {
        if (refundDtoList == null || refundDtoList.isEmpty()) {
            return Collections.emptyList();
        }

        List<OrderTransDataPo> transDataPos = new ArrayList<>(refundDtoList.size());

        for (OrderRefundBusinessDto refundDto : refundDtoList) {
            OrderTransDataPo transDataPo = new OrderTransDataPo();
            setComFields(transDataPo, businessDto, resultOrder);
            transDataPo.setBillType(ComEnums.BillTypeEnum.REFUND_ORDER.getCode());
            transDataPo.setBusinessRefundNo(refundDto.getRefundOrderNo());
            transDataPo.setRefundPayAmount(AmountCastUtil.castYuan2Fen(refundDto.getRefundFee()));
            transDataPo.setRefundPayCashAmount(AmountCastUtil.castYuan2Fen(refundDto.getCashPayAmount()));
            transDataPo.setRefundVirtualGoldAmount(AmountCastUtil.castYuan2Fen(refundDto.getVirtualGold()));
            transDataPos.add(transDataPo);
        }
        return transDataPos;
    }

    private static void setComFields(OrderTransDataPo transDataPo, OrderPayBusinessDto businessDto, PayResultOrder resultOrder) {
        transDataPo.setSellerId(businessDto.getOrgId());
        transDataPo.setSellerName(businessDto.getOrgName());
        transDataPo.setPayChannel(resultOrder.getPayChannel());
        transDataPo.setCustCode(businessDto.getMerchantId() == null ? "" : businessDto.getMerchantId().toString());
        transDataPo.setCustName(businessDto.getMerchantName());
        transDataPo.setChannelTransactionNo(resultOrder.getChannelTransactionNo());
        transDataPo.setBusinessOrderNo(businessDto.getOrderNo());
        transDataPo.setPayNo(resultOrder.getPayNo());
        transDataPo.setPaySuccessTime(businessDto.getPayTime() == null ? new Date() : businessDto.getPayTime());
        transDataPo.setPayAmount(AmountCastUtil.castYuan2Fen(businessDto.getMoney()));
        transDataPo.setPayCashAmount(AmountCastUtil.castYuan2Fen(businessDto.getCashPayAmount()));
        transDataPo.setVirtualGoldAmount(AmountCastUtil.castYuan2Fen(businessDto.getVirtualGold()));
        transDataPo.setCreateTime(new Date());
    }

    public static Tuple2<LoanRepayPlanPo, List<LoanRepayPlanDetailPo>> convertToRepayPo(LoanInfoResponse response, String businessOrderNo) {
        if (response == null) {
            return new Tuple2<>(null, Collections.emptyList());
        }
        LoanRepayPlanPo repayPlanPo = new LoanRepayPlanPo();
        repayPlanPo.setLoanNo(response.getContractNo() == null ? "" : response.getContractNo());
        repayPlanPo.setPayNo(response.getOrderCode());
        AssertUtil.notBlank(businessOrderNo, response.getOrderCode() + "交易号未找到对应订单号");
        repayPlanPo.setBusinessOrderNo(businessOrderNo);
        Integer loanStatus = ComEnums.LoanStatusEnum.getCodeByThirdCode(response.getLoanStatus());
        AssertUtil.notNull(loanStatus, "无法识别的借款单状态" + response.getLoanStatus());
        repayPlanPo.setLoanStatus(loanStatus);
        BigDecimal preSettleAmt = response.getPerSettleAmountItem() == null ? BigDecimal.ZERO : NumberUtil.emptyZero(response.getPerSettleAmountItem().getTotalAmount());
        repayPlanPo.setPreSettleAmt(preSettleAmt);
        BigDecimal paidAmt = response.getPaidAmountItem() == null ? BigDecimal.ZERO : NumberUtil.emptyZero(response.getPaidAmountItem().getTotalAmount());
        repayPlanPo.setPaidAmt(paidAmt);
        // 目前数据库是11位小数
        repayPlanPo.setDayRate(NumberUtil.str2decimalZero(response.getDayRate(), 11));
        repayPlanPo.setYearRate(NumberUtil.str2decimalZero(response.getYearRate(), 11));
        repayPlanPo.setLoanAmt(NumberUtil.emptyZero(response.getLoanAmount()));
        BigDecimal currUnPayAmt = response.getCurrUnPayAmountItem() == null ? BigDecimal.ZERO : NumberUtil.emptyZero(response.getCurrUnPayAmountItem().getTotalAmount());
        repayPlanPo.setCurrUnPayAmt(currUnPayAmt);
        repayPlanPo.setTotalPlan(NumberUtil.emptyZero(response.getTotalPlan()));
        BigDecimal dueUnPayAmt = response.getDueUnPayAmountItem() == null ? BigDecimal.ZERO : NumberUtil.emptyZero(response.getDueUnPayAmountItem().getTotalAmount());
        repayPlanPo.setDueUnPayAmt(dueUnPayAmt);
        Date now = new Date();
        repayPlanPo.setCreateTime(now);
        repayPlanPo.setUpdateTime(now);

        // 组装明细数据
        if (CollUtil.isEmpty(response.getRepayPlanList())) {
            return new Tuple2<>(repayPlanPo, Collections.emptyList());
        }

        List<LoanRepayPlanDetailPo> repayPlanDetailPos = new ArrayList<>(response.getRepayPlanList().size());
        for (RepayPlan repayPlan : response.getRepayPlanList()) {
            LoanRepayPlanDetailPo repayPlanDetailPo = new LoanRepayPlanDetailPo();
            repayPlanDetailPo.setLoanNo(repayPlanPo.getLoanNo());
            repayPlanDetailPo.setPayNo(repayPlanPo.getPayNo());
            repayPlanDetailPo.setTermNo(repayPlan.getTermNo());
            repayPlanDetailPo.setCurrTerm(Boolean.TRUE.equals(repayPlan.getCurrTerm()) ? 1 : 0);
            Integer planStatus = ComEnums.LoanStatusEnum.getCodeByThirdCode(repayPlan.getPlanStatus());
            AssertUtil.notNull(planStatus, "无法识别的分期单状态" + repayPlan.getPlanStatus());
            repayPlanDetailPo.setPlanStatus(ComEnums.LoanStatusEnum.getCodeByThirdCode(repayPlan.getPlanStatus()));
            repayPlanDetailPo.setStartDate(DateUtil.parse(repayPlan.getStartDate(), DatePattern.PURE_DATETIME_FORMAT));
            repayPlanDetailPo.setEndDate(DateUtil.parse(repayPlan.getEndDate(), DatePattern.PURE_DATETIME_FORMAT));
            if (StringUtils.isNotBlank(repayPlan.getFinishDate())) {
                repayPlanDetailPo.setFinishDate(DateUtil.parse(repayPlan.getFinishDate(), DatePattern.PURE_DATETIME_FORMAT));
            }
            repayPlanDetailPo.setOverDueStartDate(DateUtil.parse(repayPlan.getOverDueStartDate(), DatePattern.PURE_DATETIME_FORMAT));
            BigDecimal detailPaidAmt = repayPlan.getPaidAmountItem() == null ? BigDecimal.ZERO : NumberUtil.emptyZero(repayPlan.getPaidAmountItem().getTotalAmount());
            repayPlanDetailPo.setPaidAmt(detailPaidAmt);
            BigDecimal detailCurrUnPayAmt = repayPlan.getCurrUnPayAmountItem() == null ? BigDecimal.ZERO : NumberUtil.emptyZero(repayPlan.getCurrUnPayAmountItem().getTotalAmount());
            repayPlanDetailPo.setCurrUnPayAmt(detailCurrUnPayAmt);
            BigDecimal detailDueUnPayAmt = repayPlan.getDueUnPayAmountItem() == null ? BigDecimal.ZERO : NumberUtil.emptyZero(repayPlan.getDueUnPayAmountItem().getTotalAmount());
            repayPlanDetailPo.setDueUnPayAmt(detailDueUnPayAmt);
            repayPlanDetailPo.setCreateTime(now);
            repayPlanDetailPo.setUpdateTime(now);
            repayPlanDetailPos.add(repayPlanDetailPo);
        }

        return new Tuple2<>(repayPlanPo, repayPlanDetailPos);
    }

    public static OrderTransDataPo buildOrderTransDataPo(PayDO payDO, PayResultOrder payResultOrder, OrderTransDto orderTransDto) {
        OrderTransDataPo orderTransDataPo = new OrderTransDataPo();

        orderTransDataPo.setSellerId(orderTransDto.getOrgId());
        orderTransDataPo.setSellerName(orderTransDto.getCompanyName());
        orderTransDataPo.setPayChannel(payResultOrder.getPayChannel());
        orderTransDataPo.setChannelTransactionNo(payDO.getChannelTransactionNo());
        if (orderTransDto.getMerchantId() != null) {
            orderTransDataPo.setCustCode(String.valueOf(orderTransDto.getMerchantId()));
        }
        orderTransDataPo.setCustName(orderTransDto.getMerchantName());
        orderTransDataPo.setBusinessOrderNo(orderTransDto.getOrderNo());
        orderTransDataPo.setPayNo(payResultOrder.getPayNo());
        orderTransDataPo.setPaySuccessTime(payDO.getTimePaid());
        orderTransDataPo.setUscc(payDO.getUscc());
        orderTransDataPo.setPayName(payDO.getPayName());
        orderTransDataPo.setPayAccount(payDO.getPayAcc());
        orderTransDataPo.setPayAmount(AmountCastUtil.castYuan2Fen(orderTransDto.getMoney()));
        orderTransDataPo.setBillType(ComEnums.BillTypeEnum.ORDER.getCode());
        orderTransDataPo.setPayCashAmount(payResultOrder.getAmount() == null ? 0 : payResultOrder.getAmount());
        orderTransDataPo.setVirtualGoldAmount(AmountCastUtil.castYuan2Fen(orderTransDto.getVirtualGoldAmount()));
        orderTransDataPo.setCreateTime(new Date());
        return orderTransDataPo;
    }

    public static OrderTransDataPo buildRefundTransDataPo(OrderTransDataPo transDataPo, OrderRefundDto orderRefundDto) {
        OrderTransDataPo refundTransDataPo = new OrderTransDataPo();
        refundTransDataPo.setSellerId(transDataPo.getSellerId());
        refundTransDataPo.setSellerName(transDataPo.getSellerName());
        refundTransDataPo.setPayChannel(transDataPo.getPayChannel());
        refundTransDataPo.setChannelTransactionNo(transDataPo.getChannelTransactionNo());
        refundTransDataPo.setCustCode(transDataPo.getCustCode());
        refundTransDataPo.setCustName(transDataPo.getCustName());
        refundTransDataPo.setBusinessOrderNo(transDataPo.getBusinessOrderNo());
        refundTransDataPo.setPayNo(transDataPo.getPayNo());
        refundTransDataPo.setPaySuccessTime(transDataPo.getPaySuccessTime());
        refundTransDataPo.setUscc(transDataPo.getUscc());
        refundTransDataPo.setPayName(transDataPo.getPayName());
        refundTransDataPo.setPayAccount(transDataPo.getPayAccount());
        refundTransDataPo.setPayAmount(transDataPo.getPayAmount());
        refundTransDataPo.setPayCashAmount(transDataPo.getPayCashAmount());
        refundTransDataPo.setVirtualGoldAmount(transDataPo.getVirtualGoldAmount());
        refundTransDataPo.setCreateTime(new Date());

        refundTransDataPo.setBillType(ComEnums.BillTypeEnum.REFUND_ORDER.getCode());
        refundTransDataPo.setBusinessRefundNo(orderRefundDto.getRefundOrderNo());
        refundTransDataPo.setRefundPayAmount(AmountCastUtil.castYuan2Fen(orderRefundDto.getRefundFee()));
        refundTransDataPo.setRefundPayCashAmount(AmountCastUtil.castYuan2Fen(orderRefundDto.getCashPayAmount()));
        refundTransDataPo.setRefundVirtualGoldAmount(AmountCastUtil.castYuan2Fen(orderRefundDto.getVirtualGold()));
        return refundTransDataPo;
    }

    public static LoanRepayPlanPo buildUpdateRepayPlanPo(LoanInfoResponse response, LoanRepayPlanPo repayPlanPo) {
        LoanRepayPlanPo updateRepayPlanPo = new LoanRepayPlanPo();
        updateRepayPlanPo.setId(repayPlanPo.getId());

        Integer loanStatus = ComEnums.LoanStatusEnum.getCodeByThirdCode(response.getLoanStatus());
        AssertUtil.notNull(loanStatus, "无法识别的借款单状态" + response.getLoanStatus());
        updateRepayPlanPo.setLoanStatus(loanStatus);
        if (response.getPerSettleAmountItem() != null && response.getPerSettleAmountItem().getTotalAmount() != null) {
            updateRepayPlanPo.setPreSettleAmt(response.getPerSettleAmountItem().getTotalAmount());
        }
        if (response.getPaidAmountItem() != null && response.getPaidAmountItem().getTotalAmount() != null) {
            updateRepayPlanPo.setPaidAmt(response.getPaidAmountItem().getTotalAmount());
        }

        // 目前数据库是11位小数
        if (response.getDayRate() != null) {
            updateRepayPlanPo.setDayRate(NumberUtil.str2decimalZero(response.getDayRate(), 11));
        }
        if (response.getYearRate() != null) {
            updateRepayPlanPo.setYearRate(NumberUtil.str2decimalZero(response.getYearRate(), 11));
        }

        updateRepayPlanPo.setLoanAmt(response.getLoanAmount());
        if (response.getCurrUnPayAmountItem() != null && response.getCurrUnPayAmountItem().getTotalAmount() != null) {
            updateRepayPlanPo.setCurrUnPayAmt(response.getCurrUnPayAmountItem().getTotalAmount());
        }
        updateRepayPlanPo.setTotalPlan(response.getTotalPlan());
        if (response.getDueUnPayAmountItem() != null && response.getDueUnPayAmountItem().getTotalAmount() != null) {
            updateRepayPlanPo.setDueUnPayAmt(response.getDueUnPayAmountItem().getTotalAmount());
        }
        updateRepayPlanPo.setUpdateTime(new Date());

        return updateRepayPlanPo;
    }

    public static List<LoanRepayPlanDetailPo> buildUpdatePlanDetailList(LoanInfoResponse response, List<LoanRepayPlanDetailPo> planDetailPos) {
        List<LoanRepayPlanDetailPo> updatePlanDetails = new ArrayList<>();
        Map<Integer, RepayPlan> termNoMap = response.getRepayPlanList().stream().collect(Collectors.toMap(p -> p.getTermNo(), p -> p, (o, n) -> o));

        Date now = new Date();
        for (LoanRepayPlanDetailPo planDetailPo : planDetailPos) {
            if (ComEnums.LoanStatusEnum.FINISH.getCode().equals(planDetailPo.getPlanStatus())) {
                continue;
            }
            LoanRepayPlanDetailPo updatePlanDetail = new LoanRepayPlanDetailPo();
            updatePlanDetail.setId(planDetailPo.getId());
            RepayPlan repayPlan = termNoMap.get(planDetailPo.getTermNo());

            AssertUtil.notNull(repayPlan, "无效的期号" + planDetailPo.getTermNo());
            updatePlanDetail.setCurrTerm(Boolean.TRUE.equals(repayPlan.getCurrTerm()) ? 1 : 0);
            Integer planStatus = ComEnums.LoanStatusEnum.getCodeByThirdCode(repayPlan.getPlanStatus());
            AssertUtil.notNull(planStatus, "无法识别的分期单状态" + repayPlan.getPlanStatus());
            updatePlanDetail.setPlanStatus(ComEnums.LoanStatusEnum.getCodeByThirdCode(repayPlan.getPlanStatus()));
            updatePlanDetail.setStartDate(DateUtil.parse(repayPlan.getStartDate(), DatePattern.PURE_DATETIME_FORMAT));
            updatePlanDetail.setEndDate(DateUtil.parse(repayPlan.getEndDate(), DatePattern.PURE_DATETIME_FORMAT));
            if (StringUtils.isNotBlank(repayPlan.getFinishDate())) {
                updatePlanDetail.setFinishDate(DateUtil.parse(repayPlan.getFinishDate(), DatePattern.PURE_DATETIME_FORMAT));
            }
            updatePlanDetail.setOverDueStartDate(DateUtil.parse(repayPlan.getOverDueStartDate(), DatePattern.PURE_DATETIME_FORMAT));
            if (repayPlan.getPaidAmountItem() != null && repayPlan.getPaidAmountItem().getTotalAmount() != null){
                updatePlanDetail.setPaidAmt(repayPlan.getPaidAmountItem().getTotalAmount());
            }
            if (repayPlan.getCurrUnPayAmountItem() != null && repayPlan.getCurrUnPayAmountItem().getTotalAmount() != null){
                updatePlanDetail.setCurrUnPayAmt(repayPlan.getCurrUnPayAmountItem().getTotalAmount());
            }
            if (repayPlan.getDueUnPayAmountItem() != null && repayPlan.getDueUnPayAmountItem().getTotalAmount() != null){
                updatePlanDetail.setDueUnPayAmt(repayPlan.getDueUnPayAmountItem().getTotalAmount());
            }
            updatePlanDetail.setUpdateTime(now);
            updatePlanDetails.add(updatePlanDetail);
        }
        return updatePlanDetails;
    }
}
